package com.sl.sdn.repository.impl;

import cn.hutool.core.util.StrUtil;
import com.sl.sdn.dto.TransportLineNodeDTO;
import com.sl.sdn.entity.node.AgencyEntity;
import com.sl.sdn.repository.TransportLineRepository;
import com.sl.sdn.utils.TransportLineUtil;
import org.springframework.data.neo4j.core.Neo4jClient;
import org.springframework.data.neo4j.core.schema.Node;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Optional;

@Component
public class TransportLineRepositoryImpl implements TransportLineRepository {

    @Resource
    private Neo4jClient neo4jClient;

    @Override
    public TransportLineNodeDTO findShortestPath(AgencyEntity start, AgencyEntity end) {
        //获取网点数据在Neo4j中的类型
        String type = AgencyEntity.class.getAnnotation(Node.class).value()[0];
        //构造查询语句
        String cypherQuery = StrUtil.format("MATCH path = shortestPath((start:{}) -[*..10]-> (end:{}))\n" +
                "WHERE start.bid = $startId AND end.bid = $endId \n" +
                "RETURN path", type, type);

        //执行查询
        Optional<TransportLineNodeDTO> optional = this.neo4jClient.query(cypherQuery)
                .bind(start.getBid()).to("startId") //设置参数
                .bind(end.getBid()).to("endId")//设置参数
                .fetchAs(TransportLineNodeDTO.class) //设置响应数据类型
                .mappedBy((typeSystem, record) -> { //对结果进行封装处理
                    return TransportLineUtil.getTransportLine(record);
                }).one();

        return optional.orElse(null);
    }

    @Override
    public TransportLineNodeDTO findLowCostPath(AgencyEntity start, AgencyEntity end) {
        //获取网点数据在Neo4j中的类型
        String type = AgencyEntity.class.getAnnotation(Node.class).value()[0];
        //构造查询语句
        String cypherQuery = StrUtil.format("MATCH path = shortestPath((start:{}) -[*..10]-> (end:{}))\n" +
                "WHERE start.bid = $startId AND end.bid = $endId \n" +
                "UNWIND relationships(path) AS r\n" +
                "WITH sum(r.cost) AS cost, path\n" +
                "RETURN path ORDER BY cost ASC, LENGTH(path) ASC LIMIT 1", type, type);
        //执行查询
        Optional<TransportLineNodeDTO> optional = this.neo4jClient.query(cypherQuery)
                .bind(start.getBid()).to("startId") //设置参数
                .bind(end.getBid()).to("endId")//设置参数
                .fetchAs(TransportLineNodeDTO.class) //设置响应数据类型
                .mappedBy((typeSystem, record) -> { //对结果进行封装处理
                    return TransportLineUtil.getTransportLine(record);
                }).one();
        return optional.orElse(null);
    }
}
